namespace chatroom{
    // 1  brpc服务端
    class TransmiteServiceImp : public chatroom::MsgTransmitService{
    public:
        TransmiteServiceImp( std::string user_serivce_name,
        std::string exchange_name,
        std::shared_ptr<ChatSessionMemTable> chat_session_table,
        chatroom::MqClient::Ptr Mq_client,
        chatroom::ServiceManage::Sptr mm_channel):
        _user_serivce_name(user_serivce_name),
        _exchange_name(exchange_name),
        _chat_session_table(chat_session_id),
        _Mq_client(Mq_client),
        _mm_channel(mm_channel){}
        ~TransmiteServiceImp(){}
        virtual void GetTransmitTarget(::google::protobuf::RpcController* controller,
                       const ::chatroom::NewMessageReq* request,
                       ::chatroom::GetTransmitTargetRsp* response,
                       ::google::protobuf::Closure* done){
                    brpc::ClosureGuard guard(done);
                    auto errmsg_response = [this,response](const std::string& rid,const std::string& errmsg) ->void{
                                    response->set_success(false);
                                    response->set_request_id(rid);
                                    request->set_errmsg(errmsg);
                                    return;
                    }
                    // 1. 从请求中取出消息内容，会话 ID， 用户 ID
                    std::string chat_ssid = request->chat_session_id();
                    std::string user_id = request->user_id();
                    MessageContent& msg = request->message();
                    // 2. 根据用户 ID 从用户子服务获取当前发送者用户信息
                    auto channel = _mm_channel->choose(_user_serivce_name);
                    if(!channel)
                    {
                        Logger_ERROR("{}没有存在对应的用户子服务节点",request->request_id());
                        return errmsg_response(request->request_id(),"没有存在对应的用户子服务节点");
                    }
                    chatroom::UserService_Stub stub(channel.get());
                    brpc::Controller* cntl = new brpc::Controller();
                    chatroom::GetUserInfoReq req;
                    chatroom::GetUserInfoRsp rsp;
                    req.set_request_id(request->request_id());
                    req.set_user_id(user_id);
                    //同步调用用户子服务获取用户的完整信息
                    stub.GetUserInfo(cntl,req,rsp,nullptr);
                    if(cntl->Failed())
                    {
                        Logger_ERROR("{}用户子服务调用失败,{}",request_>request_id(),cntl->ErrorText());
                        delete cntl;
                        return errmsg_response(request->request_id(),"用户子服务调用失败");
                    }
                    auto user_info = rsp.user_info();
                    // 3. 根据消息内容构造完成的消息结构（分配消息 ID，填充发送者信息，填充消息产生时间）
                    MessageInfo info;
                    info.set_message_id(uuid());
                    info.set_chat_session_id(chat_ssid);
                    info.set_timestamp(time(nullptr));
                    info.mutable_sender->CopyFrom(user_info);
                    info.mutable_message->CopyFrom(msg);
                    // 4. 将消息序列化后发布到 MQ 消息队列中，让消息存储子服务对消息进行持久化存储
                    bool ret = _Mq_client->publish(_exchange_name,msg.SerializeAsString());
                    if(!ret)
                    {
                        Logger_ERROR("放入消息队列失败");
                        return errmsg_response(request->request_id(),"放入消息队列失败");
                    }
                    // 5. 从数据库获取目标会话所有成员 ID
                    auto users = _chat_session_table->get_all(chat_ssid);
                    // 6. 组织响应（完整消息+目标用户 ID），发送给网关，告知网关该将消息发送给谁。
                    response->set_request_id(request->request_id());
                    response->set_success(true);
                    response->mutable_message()->CopyFrom(info);
                    for(auto& id : users)
                    {
                        response->add_target_id_list(id);
                    }
                }
    private:
        std::string _user_serivce_name;
        std::string _exchange_name;
        std::shared_ptr<ChatSessionMemTable> _chat_session_table;
        chatroom::MqClient::Ptr _Mq_client;
        chatroom::ServiceManage::Sptr _mm_channel;
    };
    class TransmiteServer{
        public:
            using ptr = std::shared_ptr<TransmiteServer>
            TransmiteServer( std::shared_ptr<odb::core::database> sql_client,
            std::shared_ptr<brpc::Server> server,
            chatroom::Registery::ptr rclient,
            chatroom::Discovery::ptr discover_client,
            std::string user_serivce_name,
            chatroom::ServiceManage::Sptr mm_channel,
            std::string exchange_name,
            std::string queue_name,
            chatroom::MqClient::Ptr Mq_client)
            :_sql_client(sql_client),_server(server)
            ,_rclient(rclient),_discover_client(discover_client),
            _user_serivce_name(user_serivce_name),_mm_channel(mm_channel),
            _exchange_name(exchange_name),_queue_name(queue_name)(){}
            ~TransmiteServer(){}
            void start(){
                _server->RunUntilAskedToQuit();
            }
        private:           
            std::shared_ptr<odb::core::database> _sql_client;
            std::shared_ptr<brpc::Server> _server;
            chatroom::Registery::ptr _rclient;
            chatroom::Discovery::ptr _discover_client;
            std::string _user_serivce_name;
            chatroom::ServiceManage::Sptr _mm_channel;
            std::string _exchange_name;
            std::string _queue_name;
            chatroom::MqClient::Ptr _Mq_client;
    };
    class TransmiteServerBuild{
        public:
            //实例化服务发现
            void make_discover_object(const std::string& host,std::string& basedir,std::string& user_serivce_name)
            {
                _mm_channel =  std::make_shared<ServiceManage>();
                _mm_channel->declare(user_serivce_name);
                _user_serivce_name = user_serivce_name;
                auto put_cb = std::bind(&ServiceManage::ServiceOnline,_mm_channel.get(),std::placeholders::_1,std::placeholders::_2);
                auto off_cb = std::bind(&ServiceManage::ServiceOffline,_mm_channel.get(),std::placeholders::_1,std::placeholders::_2);
                _discover_client = make_shared<Discovery>(host,basedir,put_cb,off_cb);
            }
            //实例化mq客户端
            void make_MQ_client(const std::string& user,const std::string& pswd,const std::string& host,
            const std::string& exchange_name,const std::string& queue_name)
            {
                _exchange_name = exchange_name;
                _queue_name = queue_name;
                _Mq_client = std::make_shared<MqClient>(user,pswd,host);
                _Mq_client->EQbind(exchange_name,queue_name);
            }
            //实例化sql客户端
            void make_sql_client(const std::string& user,
            const std::string &pswd,
            const std::string &host,
            const std::string &db,
            const std::string &cset,
            int port,
            int conn_pool_count){
                _sql_client = chatroom::DBFactory::create(user,pswd,host,db,cset,port,conn_pool_count);
            }
            void make_rpc_server(int32_t port,int32_t timeout,int32_t num_threads)
            {
                _server = std::make_shared<brpc::Server>();
                //3 往服务器中添加服务
                TransmiteServiceImp* transmite = new TransmiteServiceImp(
                            // std::string _user_serivce_name;
                            // std::string _exchange_name;
                            // std::shared_ptr<ChatSessionMemTable> _chat_session_table;
                            // chatroom::MqClient::Ptr _Mq_client;
                            // chatroom::ServiceManage::Sptr _mm_channel;
                            _user_serivce_name,_exchange_name,std::make_shared<ChatSessionMemTable>(_sql_client),
                            _Mq_client,_mm_channel
                );
                int ret = _server->AddService(speech,brpc::ServiceOwnership::SERVER_OWNS_SERVICE);
                if(ret == -1)
                {
                    Logger_ERROR("添加服务失败");
                    abort();
                }
                //4 启动服务器
                brpc::ServerOptions options;
                options.idle_timeout_sec = timeout; //指定超时连接时间，-1表示超时一直在连接着
                options.num_threads = num_threads;//cpu线程数量
                ret = _server->Start(port,&options);
                if(ret == -1)
                {
                    Logger_ERROR("启动服务器失败");
                    abort();
                }
            }
            void  make_reg_object(std::string& register_host,const std::string& hostname,std::string& access_host)
            {
                _rclient = std::make_shared<chatroom::Registery>(register_host);
                _rclient->Register(hostname,access_host);
            }
            TransmiteServer::ptr build()
            {
                if(!_server){
                    Logger_ERROR("RPC服务子模块没有初始化");
                    abort();
                }
                if(!_rclient){
                    Logger_ERROR("注册服务没有初始化");
                    abort();
                }
                return std::make_shared<TransmiteServer>(_client,_server,_rclient);
            }
        private:
            std::shared_ptr<odb::core::database> _sql_client;
            std::shared_ptr<brpc::Server> _server;
            chatroom::Registery::ptr _rclient;
            chatroom::Discovery::ptr _discover_client;
            std::string _user_serivce_name;
            chatroom::ServiceManage::Sptr _mm_channel;
            std::string _exchange_name;
            std::string _queue_name;
            chatroom::MqClient::Ptr _Mq_client;
    };
}